/*-------------------------------------------------------------------------
 *
 * rangetypes.c
 *	  范围类型的输入/输出函数、操作符和支持函数。
 *
 * 范围值的存储（序列化）格式是：
 *
 *	4 字节：varlena 头部
 *	4 字节：范围类型的 OID
 *	下边界值（如果有），按照子类型的 typalign 对齐
 *	上边界值（如果有），按照子类型的 typalign 对齐
 *	1 字节用于标志
 *
 * 该表示法选择避免在下边界值之前需要任何填充，
 * 即使这需要双重对齐。我们可以期待 varlena 头部
 * 以合适的对齐边界呈现给我们（可能在去除变形后），
 * 然后下边界也是如此。请注意，这意味着我们不能使用
 * 填充的（短的 varlena 头部）值；我们必须首先将其去除变形。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/utils/adt/rangetypes.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/tupmacs.h"
#include "common/hashfn.h"
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/lsyscache.h"
#include "utils/rangetypes.h"
#include "utils/timestamp.h"


/* 一个范围 I/O 函数的 fn_extra 缓存条目 */
typedef struct RangeIOData
{
	TypeCacheEntry *typcache;	/* 范围类型的 typcache 条目 */
	FmgrInfo	typioproc;		/* 元素类型的 I/O 函数 */
	Oid			typioparam;		/* 元素类型的 I/O 参数 */
} RangeIOData;


static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid fc_rngtypid,
									  IOFuncSelector fc_func);
static char fc_range_parse_flags(const char *fc_flags_str);
static void fc_range_parse(const char *fc_input_str, char *fc_flags, char **fc_lbound_str,
						char **fc_ubound_str);
static const char *fc_range_parse_bound(const char *fc_string, const char *fc_ptr,
									 char **fc_bound_str, bool *fc_infinite);
static char *fc_range_deparse(char fc_flags, const char *fc_lbound_str,
						   const char *fc_ubound_str);
static char *fc_range_bound_escape(const char *fc_value);
static Size fc_datum_compute_size(Size fc_sz, Datum fc_datum, bool fc_typbyval,
							   char fc_typalign, int16 fc_typlen, char fc_typstorage);
static Pointer fc_datum_write(Pointer fc_ptr, Datum fc_datum, bool fc_typbyval,
						   char fc_typalign, int16 fc_typlen, char fc_typstorage);


/*
 * ----------------------------------------------------------
 * I/O 函数
 * ----------------------------------------------------------
 */

Datum range_in(PG_FUNCTION_ARGS)
{
	char	   *fc_input_str = PG_GETARG_CSTRING(0);
	Oid			fc_rngtypoid = PG_GETARG_OID(1);
	Oid			fc_typmod = PG_GETARG_INT32(2);
	RangeType  *fc_range;
	RangeIOData *fc_cache;
	char		fc_flags;
	char	   *fc_lbound_str;
	char	   *fc_ubound_str;
	RangeBound	fc_lower;
	RangeBound	fc_upper;

	check_stack_depth();		/* 当子类型为范围类型时递归 */

	fc_cache = get_range_io_data(fcinfo, fc_rngtypoid, IOFunc_input);

	/* parse */
	fc_range_parse(fc_input_str, &fc_flags, &fc_lbound_str, &fc_ubound_str);

	/* 调用元素类型的输入函数 */
	if (RANGE_HAS_LBOUND(fc_flags))
		fc_lower.val = InputFunctionCall(&fc_cache->typioproc, fc_lbound_str,
									  fc_cache->typioparam, fc_typmod);
	if (RANGE_HAS_UBOUND(fc_flags))
		fc_upper.val = InputFunctionCall(&fc_cache->typioproc, fc_ubound_str,
									  fc_cache->typioparam, fc_typmod);

	fc_lower.infinite = (fc_flags & RANGE_LB_INF) != 0;
	fc_lower.inclusive = (fc_flags & RANGE_LB_INC) != 0;
	fc_lower.lower = true;
	fc_upper.infinite = (fc_flags & RANGE_UB_INF) != 0;
	fc_upper.inclusive = (fc_flags & RANGE_UB_INC) != 0;
	fc_upper.lower = false;

	/* 序列化和规范化 */
	fc_range = make_range(fc_cache->typcache, &fc_lower, &fc_upper, fc_flags & RANGE_EMPTY);

	PG_RETURN_RANGE_P(fc_range);
}

Datum range_out(PG_FUNCTION_ARGS)
{
	RangeType  *fc_range = PG_GETARG_RANGE_P(0);
	char	   *fc_output_str;
	RangeIOData *fc_cache;
	char		fc_flags;
	char	   *fc_lbound_str = NULL;
	char	   *fc_ubound_str = NULL;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	check_stack_depth();		/* 当子类型为范围类型时递归 */

	fc_cache = get_range_io_data(fcinfo, RangeTypeGetOid(fc_range), IOFunc_output);

	/* 反序列化 */
	range_deserialize(fc_cache->typcache, fc_range, &fc_lower, &fc_upper, &fc_empty);
	fc_flags = range_get_flags(fc_range);

	/* 调用元素类型的输出函数 */
	if (RANGE_HAS_LBOUND(fc_flags))
		fc_lbound_str = OutputFunctionCall(&fc_cache->typioproc, fc_lower.val);
	if (RANGE_HAS_UBOUND(fc_flags))
		fc_ubound_str = OutputFunctionCall(&fc_cache->typioproc, fc_upper.val);

	/* 构建结果字符串 */
	fc_output_str = fc_range_deparse(fc_flags, fc_lbound_str, fc_ubound_str);

	PG_RETURN_CSTRING(fc_output_str);
}

/*
 * 二进制表示：第一个字节是标志，然后是下界
 * （如果存在），接着是上界（如果存在）。每个界限由一个 4 字节长度头
 * 和该界限的二进制表示（由对子类型的发送函数的调用返回）表示。
 */

Datum range_recv(PG_FUNCTION_ARGS)
{
	StringInfo	fc_buf = (StringInfo) PG_GETARG_POINTER(0);
	Oid			fc_rngtypoid = PG_GETARG_OID(1);
	int32		fc_typmod = PG_GETARG_INT32(2);
	RangeType  *fc_range;
	RangeIOData *fc_cache;
	char		fc_flags;
	RangeBound	fc_lower;
	RangeBound	fc_upper;

	check_stack_depth();		/* 当子类型为范围类型时递归 */

	fc_cache = get_range_io_data(fcinfo, fc_rngtypoid, IOFunc_receive);

	/* 接收标志... */
	fc_flags = (unsigned char) pq_getmsgbyte(fc_buf);

	/*
	 * 屏蔽任何不支持的标志，特别是 RANGE_xB_NULL，这将
	 * 混淆后续测试。请注意，range_serialize 将处理
	 * 清理剩余标志中的任何不一致性。
	 */
	fc_flags &= (RANGE_EMPTY |
			  RANGE_LB_INC |
			  RANGE_LB_INF |
			  RANGE_UB_INC |
			  RANGE_UB_INF);

	/* 接收界限... */
	if (RANGE_HAS_LBOUND(fc_flags))
	{
		uint32		fc_bound_len = pq_getmsgint(fc_buf, 4);
		const char *fc_bound_data = pq_getmsgbytes(fc_buf, fc_bound_len);
		StringInfoData fc_bound_buf;

		initStringInfo(&fc_bound_buf);
		appendBinaryStringInfo(&fc_bound_buf, fc_bound_data, fc_bound_len);

		fc_lower.val = ReceiveFunctionCall(&fc_cache->typioproc,
										&fc_bound_buf,
										fc_cache->typioparam,
										fc_typmod);
		pfree(fc_bound_buf.data);
	}
	else
		fc_lower.val = (Datum) 0;

	if (RANGE_HAS_UBOUND(fc_flags))
	{
		uint32		fc_bound_len = pq_getmsgint(fc_buf, 4);
		const char *fc_bound_data = pq_getmsgbytes(fc_buf, fc_bound_len);
		StringInfoData fc_bound_buf;

		initStringInfo(&fc_bound_buf);
		appendBinaryStringInfo(&fc_bound_buf, fc_bound_data, fc_bound_len);

		fc_upper.val = ReceiveFunctionCall(&fc_cache->typioproc,
										&fc_bound_buf,
										fc_cache->typioparam,
										fc_typmod);
		pfree(fc_bound_buf.data);
	}
	else
		fc_upper.val = (Datum) 0;

	pq_getmsgend(fc_buf);

	/* 完成构建 RangeBound 表示 */
	fc_lower.infinite = (fc_flags & RANGE_LB_INF) != 0;
	fc_lower.inclusive = (fc_flags & RANGE_LB_INC) != 0;
	fc_lower.lower = true;
	fc_upper.infinite = (fc_flags & RANGE_UB_INF) != 0;
	fc_upper.inclusive = (fc_flags & RANGE_UB_INC) != 0;
	fc_upper.lower = false;

	/* 序列化和规范化 */
	fc_range = make_range(fc_cache->typcache, &fc_lower, &fc_upper, fc_flags & RANGE_EMPTY);

	PG_RETURN_RANGE_P(fc_range);
}

Datum range_send(PG_FUNCTION_ARGS)
{
	RangeType  *fc_range = PG_GETARG_RANGE_P(0);
	StringInfo	fc_buf = makeStringInfo();
	RangeIOData *fc_cache;
	char		fc_flags;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	check_stack_depth();		/* 当子类型为范围类型时递归 */

	fc_cache = get_range_io_data(fcinfo, RangeTypeGetOid(fc_range), IOFunc_send);

	/* 反序列化 */
	range_deserialize(fc_cache->typcache, fc_range, &fc_lower, &fc_upper, &fc_empty);
	fc_flags = range_get_flags(fc_range);

	/* 构造输出 */
	pq_begintypsend(fc_buf);

	pq_sendbyte(fc_buf, fc_flags);

	if (RANGE_HAS_LBOUND(fc_flags))
	{
		Datum		fc_bound = PointerGetDatum(SendFunctionCall(&fc_cache->typioproc,
															 fc_lower.val));
		uint32		fc_bound_len = VARSIZE(fc_bound) - VARHDRSZ;
		char	   *fc_bound_data = VARDATA(fc_bound);

		pq_sendint32(fc_buf, fc_bound_len);
		pq_sendbytes(fc_buf, fc_bound_data, fc_bound_len);
	}

	if (RANGE_HAS_UBOUND(fc_flags))
	{
		Datum		fc_bound = PointerGetDatum(SendFunctionCall(&fc_cache->typioproc,
															 fc_upper.val));
		uint32		fc_bound_len = VARSIZE(fc_bound) - VARHDRSZ;
		char	   *fc_bound_data = VARDATA(fc_bound);

		pq_sendint32(fc_buf, fc_bound_len);
		pq_sendbytes(fc_buf, fc_bound_data, fc_bound_len);
	}

	PG_RETURN_BYTEA_P(pq_endtypsend(fc_buf));
}

/*
 * get_range_io_data：获取范围类型 I/O 所需的缓存信息
 *
 * 范围 I/O 函数需要比其他范围函数更多的缓存信息，
 * 因此它们在 fn_extra 中存储一个 RangeIOData 结构，而不仅仅是一个
 * 指向类型缓存条目的指针。
 */
static RangeIOData *
get_range_io_data(FunctionCallInfo fcinfo, Oid fc_rngtypid, IOFuncSelector fc_func)
{
	RangeIOData *fc_cache = (RangeIOData *) fcinfo->flinfo->fn_extra;

	if (fc_cache == NULL || fc_cache->typcache->type_id != fc_rngtypid)
	{
		int16		fc_typlen;
		bool		fc_typbyval;
		char		fc_typalign;
		char		fc_typdelim;
		Oid			fc_typiofunc;

		fc_cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
												   sizeof(RangeIOData));
		fc_cache->typcache = lookup_type_cache(fc_rngtypid, TYPECACHE_RANGE_INFO);
		if (fc_cache->typcache->rngelemtype == NULL)
			elog(ERROR, "type %u is not a range type", fc_rngtypid);

		/* get_type_io_data 做的比我们需要的更多，但很方便 */
		get_type_io_data(fc_cache->typcache->rngelemtype->type_id,
						 fc_func,
						 &fc_typlen,
						 &fc_typbyval,
						 &fc_typalign,
						 &fc_typdelim,
						 &fc_cache->typioparam,
						 &fc_typiofunc);

		if (!OidIsValid(fc_typiofunc))
		{
			/* 这只能发生在接收或发送情况下 */
			if (fc_func == IOFunc_receive)
				ereport(ERROR,
						(errcode(ERRCODE_UNDEFINED_FUNCTION),
						 errmsg("no binary input function available for type %s",
								format_type_be(fc_cache->typcache->rngelemtype->type_id))));
			else
				ereport(ERROR,
						(errcode(ERRCODE_UNDEFINED_FUNCTION),
						 errmsg("no binary output function available for type %s",
								format_type_be(fc_cache->typcache->rngelemtype->type_id))));
		}
		fmgr_info_cxt(fc_typiofunc, &fc_cache->typioproc,
					  fcinfo->flinfo->fn_mcxt);

		fcinfo->flinfo->fn_extra = (void *) fc_cache;
	}

	return fc_cache;
}


/*
 *----------------------------------------------------------
 * 通用函数
 *----------------------------------------------------------
 */

/* 从两个参数构建标准形式的范围值 */
Datum range_constructor2(PG_FUNCTION_ARGS)
{
	Datum		fc_arg1 = PG_GETARG_DATUM(0);
	Datum		fc_arg2 = PG_GETARG_DATUM(1);
	Oid			fc_rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
	RangeType  *fc_range;
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;

	fc_typcache = range_get_typcache(fcinfo, fc_rngtypid);

	fc_lower.val = PG_ARGISNULL(0) ? (Datum) 0 : fc_arg1;
	fc_lower.infinite = PG_ARGISNULL(0);
	fc_lower.inclusive = true;
	fc_lower.lower = true;

	fc_upper.val = PG_ARGISNULL(1) ? (Datum) 0 : fc_arg2;
	fc_upper.infinite = PG_ARGISNULL(1);
	fc_upper.inclusive = false;
	fc_upper.lower = false;

	fc_range = make_range(fc_typcache, &fc_lower, &fc_upper, false);

	PG_RETURN_RANGE_P(fc_range);
}

/* 从三个参数构建通用范围值 */
Datum range_constructor3(PG_FUNCTION_ARGS)
{
	Datum		fc_arg1 = PG_GETARG_DATUM(0);
	Datum		fc_arg2 = PG_GETARG_DATUM(1);
	Oid			fc_rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
	RangeType  *fc_range;
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	char		fc_flags;

	fc_typcache = range_get_typcache(fcinfo, fc_rngtypid);

	if (PG_ARGISNULL(2))
		ereport(ERROR,
				(errcode(ERRCODE_DATA_EXCEPTION),
				 errmsg("range constructor flags argument must not be null")));

	fc_flags = fc_range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));

	fc_lower.val = PG_ARGISNULL(0) ? (Datum) 0 : fc_arg1;
	fc_lower.infinite = PG_ARGISNULL(0);
	fc_lower.inclusive = (fc_flags & RANGE_LB_INC) != 0;
	fc_lower.lower = true;

	fc_upper.val = PG_ARGISNULL(1) ? (Datum) 0 : fc_arg2;
	fc_upper.infinite = PG_ARGISNULL(1);
	fc_upper.inclusive = (fc_flags & RANGE_UB_INC) != 0;
	fc_upper.lower = false;

	fc_range = make_range(fc_typcache, &fc_lower, &fc_upper, false);

	PG_RETURN_RANGE_P(fc_range);
}


/* 范围 -> 子类型函数 */

/* 提取下限值 */
Datum range_lower(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	range_deserialize(fc_typcache, fc_r1, &fc_lower, &fc_upper, &fc_empty);

	/* 如果没有有限的下界则返回 NULL */
	if (fc_empty || fc_lower.infinite)
		PG_RETURN_NULL();

	PG_RETURN_DATUM(fc_lower.val);
}

/* 提取上限值 */
Datum range_upper(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	range_deserialize(fc_typcache, fc_r1, &fc_lower, &fc_upper, &fc_empty);

	/* 如果没有有限的上界则返回 NULL */
	if (fc_empty || fc_upper.infinite)
		PG_RETURN_NULL();

	PG_RETURN_DATUM(fc_upper.val);
}


/* 范围 -> 布尔函数 */

/* 范围为空吗？ */
Datum range_empty(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	char		fc_flags = range_get_flags(fc_r1);

	PG_RETURN_BOOL(fc_flags & RANGE_EMPTY);
}

/* 下限包含吗？ */
Datum range_lower_inc(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	char		fc_flags = range_get_flags(fc_r1);

	PG_RETURN_BOOL(fc_flags & RANGE_LB_INC);
}

/* 上限包含吗？ */
Datum range_upper_inc(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	char		fc_flags = range_get_flags(fc_r1);

	PG_RETURN_BOOL(fc_flags & RANGE_UB_INC);
}

/* 下限是无限吗？ */
Datum range_lower_inf(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	char		fc_flags = range_get_flags(fc_r1);

	PG_RETURN_BOOL(fc_flags & RANGE_LB_INF);
}

/* 上限是无限吗？ */
Datum range_upper_inf(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	char		fc_flags = range_get_flags(fc_r1);

	PG_RETURN_BOOL(fc_flags & RANGE_UB_INF);
}


/* 范围，元素 -> 布尔函数 */

/* 包含吗？ */
Datum range_contains_elem(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r = PG_GETARG_RANGE_P(0);
	Datum		fc_val = PG_GETARG_DATUM(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	PG_RETURN_BOOL(range_contains_elem_internal(fc_typcache, fc_r, fc_val));
}

/* 被包含吗？ */
Datum elem_contained_by_range(PG_FUNCTION_ARGS)
{
	Datum		fc_val = PG_GETARG_DATUM(0);
	RangeType  *fc_r = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	PG_RETURN_BOOL(range_contains_elem_internal(fc_typcache, fc_r, fc_val));
}


/* 范围，范围 -> 布尔函数 */

/* 相等（内部版本） */
bool range_eq_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	if (fc_empty1 && fc_empty2)
		return true;
	if (fc_empty1 != fc_empty2)
		return false;

	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) != 0)
		return false;

	if (range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2) != 0)
		return false;

	return true;
}

/* equality */
Datum range_eq(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_eq_internal(fc_typcache, fc_r1, fc_r2));
}

/* 不相等（内部版本） */
bool range_ne_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	return (!range_eq_internal(fc_typcache, fc_r1, fc_r2));
}

/* 不相等 */
Datum range_ne(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_ne_internal(fc_typcache, fc_r1, fc_r2));
}

/* 包含吗？ */
Datum range_contains(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_contains_internal(fc_typcache, fc_r1, fc_r2));
}

/* 被包含吗？ */
Datum range_contained_by(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_contained_by_internal(fc_typcache, fc_r1, fc_r2));
}

/* 严格在左边吗? (内部版本) */
bool range_before_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 空范围既不在任何其他范围之前，也不在之后 */
	if (fc_empty1 || fc_empty2)
		return false;

	return (range_cmp_bounds(fc_typcache, &fc_upper1, &fc_lower2) < 0);
}

/* 严格在左侧吗？ */
Datum range_before(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_before_internal(fc_typcache, fc_r1, fc_r2));
}

/* 严格在右边吗? (内部版本) */
bool range_after_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 空范围既不在任何其他范围之前，也不在之后 */
	if (fc_empty1 || fc_empty2)
		return false;

	return (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_upper2) > 0);
}

/* 严格在右侧吗？ */
Datum range_after(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_after_internal(fc_typcache, fc_r1, fc_r2));
}

/*
 * 检查两个边界 A 和 B 是否“相邻”，其中 A 是上边界，B 是
 * 下边界。要使边界相邻，每个子类型值必须严格满足其中一个边界：
 * 不存在满足两个边界的值（即小于 A 且大于 B）；也不存在
 * 满足两个边界都不成立的值（即大于 A 且小于 B）。
 *
 * 对于离散范围，我们依赖于规范化函数来查看 A..B 是否
 * 规范化为空。（如果没有规范化函数，那么这种范围不可能规范化为空，
 * 所以我们无需尝试。）
 *
 * 如果 A == B，只有当边界具有不同的包含标志时，这些范围才是相邻的
 * （即，恰好有一个范围包含公共边界点）。
 *
 * 如果 A > B，那么在这种顺序下这些范围并不相邻。
 */
bool bounds_adjacent(TypeCacheEntry *fc_typcache, RangeBound fc_boundA, RangeBound fc_boundB)
{
	int			fc_cmp;

	Assert(!fc_boundA.lower && fc_boundB.lower);

	fc_cmp = range_cmp_bound_values(fc_typcache, &fc_boundA, &fc_boundB);
	if (fc_cmp < 0)
	{
		RangeType  *fc_r;

		/*
		 * 边界不重叠；查看中间是否有点。
		 */

		/* 在连续子类型中，假定有点在其之间 */
		if (!OidIsValid(fc_typcache->rng_canonical_finfo.fn_oid))
			return false;

		/*
		 * 边界是离散范围类型；所以创建范围 A..B 并
		 * 查看它是否为空。
		 */

		/* 翻转包含标志 */
		fc_boundA.inclusive = !fc_boundA.inclusive;
		fc_boundB.inclusive = !fc_boundB.inclusive;
		/* 更改上/下标签以避免断言失败 */
		fc_boundA.lower = true;
		fc_boundB.lower = false;
		fc_r = make_range(fc_typcache, &fc_boundA, &fc_boundB, false);
		return RangeIsEmpty(fc_r);
	}
	else if (fc_cmp == 0)
		return fc_boundA.inclusive != fc_boundB.inclusive;
	else
		return false;			/* 边界重叠 */
}

/* 相邻（但不重叠）？（内部版本） */
bool range_adjacent_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 空范围与任何其他范围不相邻 */
	if (fc_empty1 || fc_empty2)
		return false;

	/*
	 * 给定两个范围 A..B 和 C..D，当且仅当
	 * B 与 C 相邻，或者 D 与 A 相邻时，这些范围是相邻的。
	 */
	return (bounds_adjacent(fc_typcache, fc_upper1, fc_lower2) ||
			bounds_adjacent(fc_typcache, fc_upper2, fc_lower1));
}

/* 相邻（但不重叠）？ */
Datum range_adjacent(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_adjacent_internal(fc_typcache, fc_r1, fc_r2));
}

/* 重叠？（内部版本） */
bool range_overlaps_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 空范围不与任何其他范围重叠 */
	if (fc_empty1 || fc_empty2)
		return false;

	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) >= 0 &&
		range_cmp_bounds(fc_typcache, &fc_lower1, &fc_upper2) <= 0)
		return true;

	if (range_cmp_bounds(fc_typcache, &fc_lower2, &fc_lower1) >= 0 &&
		range_cmp_bounds(fc_typcache, &fc_lower2, &fc_upper1) <= 0)
		return true;

	return false;
}

/* 是否重叠？ */
Datum range_overlaps(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_overlaps_internal(fc_typcache, fc_r1, fc_r2));
}

/* 不延伸到右侧？（内部版本） */
bool range_overleft_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 空范围既不在任何其他范围之前，也不在之后 */
	if (fc_empty1 || fc_empty2)
		return false;

	if (range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2) <= 0)
		return true;

	return false;
}

/* 不延伸到右侧吗？ */
Datum range_overleft(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_overleft_internal(fc_typcache, fc_r1, fc_r2));
}

/* 不延伸到左侧？（内部版本） */
bool range_overright_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 空范围既不在任何其他范围之前，也不在之后 */
	if (fc_empty1 || fc_empty2)
		return false;

	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) >= 0)
		return true;

	return false;
}

/* 不延伸到左侧吗？ */
Datum range_overright(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_BOOL(range_overright_internal(fc_typcache, fc_r1, fc_r2));
}


/* 范围，范围 -> 范围函数 */

/* 集合差 */
Datum range_minus(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	RangeType  *fc_ret;
	TypeCacheEntry *fc_typcache;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	fc_ret = range_minus_internal(fc_typcache, fc_r1, fc_r2);
	if (fc_ret)
		PG_RETURN_RANGE_P(fc_ret);
	else
		PG_RETURN_NULL();
}

RangeType * range_minus_internal(TypeCacheEntry *fc_typcache, RangeType *fc_r1, RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;
	int			fc_cmp_l1l2,
				fc_cmp_l1u2,
				fc_cmp_u1l2,
				fc_cmp_u1u2;

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 如果任一为空，r1 是正确答案 */
	if (fc_empty1 || fc_empty2)
		return fc_r1;

	fc_cmp_l1l2 = range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2);
	fc_cmp_l1u2 = range_cmp_bounds(fc_typcache, &fc_lower1, &fc_upper2);
	fc_cmp_u1l2 = range_cmp_bounds(fc_typcache, &fc_upper1, &fc_lower2);
	fc_cmp_u1u2 = range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2);

	if (fc_cmp_l1l2 < 0 && fc_cmp_u1u2 > 0)
		ereport(ERROR,
				(errcode(ERRCODE_DATA_EXCEPTION),
				 errmsg("result of range difference would not be contiguous")));

	if (fc_cmp_l1u2 > 0 || fc_cmp_u1l2 < 0)
		return fc_r1;

	if (fc_cmp_l1l2 >= 0 && fc_cmp_u1u2 <= 0)
		return make_empty_range(fc_typcache);

	if (fc_cmp_l1l2 <= 0 && fc_cmp_u1l2 >= 0 && fc_cmp_u1u2 <= 0)
	{
		fc_lower2.inclusive = !fc_lower2.inclusive;
		fc_lower2.lower = false;	/* 它将成为上边界 */
		return make_range(fc_typcache, &fc_lower1, &fc_lower2, false);
	}

	if (fc_cmp_l1l2 >= 0 && fc_cmp_u1u2 >= 0 && fc_cmp_l1u2 <= 0)
	{
		fc_upper2.inclusive = !fc_upper2.inclusive;
		fc_upper2.lower = true;	/* 它将成为下边界 */
		return make_range(fc_typcache, &fc_upper2, &fc_upper1, false);
	}

	elog(ERROR, "unexpected case in range_minus");
	return NULL;
}

/*
 * 集合并。 如果 strict 为真，则输入的两个范围不相邻或重叠是错误的。
 */
RangeType * range_union_internal(TypeCacheEntry *fc_typcache, RangeType *fc_r1, RangeType *fc_r2,
					 bool fc_strict)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;
	RangeBound *fc_result_lower;
	RangeBound *fc_result_upper;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 如果其中一个为空，另一个就是正确答案 */
	if (fc_empty1)
		return fc_r2;
	if (fc_empty2)
		return fc_r1;

	if (fc_strict &&
		!DatumGetBool(range_overlaps_internal(fc_typcache, fc_r1, fc_r2)) &&
		!DatumGetBool(range_adjacent_internal(fc_typcache, fc_r1, fc_r2)))
		ereport(ERROR,
				(errcode(ERRCODE_DATA_EXCEPTION),
				 errmsg("result of range union would not be contiguous")));

	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) < 0)
		fc_result_lower = &fc_lower1;
	else
		fc_result_lower = &fc_lower2;

	if (range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2) > 0)
		fc_result_upper = &fc_upper1;
	else
		fc_result_upper = &fc_upper2;

	return make_range(fc_typcache, fc_result_lower, fc_result_upper, false);
}

Datum range_union(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_RANGE_P(range_union_internal(fc_typcache, fc_r1, fc_r2, true));
}

/*
 * 范围合并：类似集合并集，但也允许并计算不相邻的
 * 输入范围。
 */
Datum range_merge(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_RANGE_P(range_union_internal(fc_typcache, fc_r1, fc_r2, false));
}

/* 集合交集 */
Datum range_intersect(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	PG_RETURN_RANGE_P(range_intersect_internal(fc_typcache, fc_r1, fc_r2));
}

RangeType * range_intersect_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;
	RangeBound *fc_result_lower;
	RangeBound *fc_result_upper;

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	if (fc_empty1 || fc_empty2 || !range_overlaps_internal(fc_typcache, fc_r1, fc_r2))
		return make_empty_range(fc_typcache);

	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) >= 0)
		fc_result_lower = &fc_lower1;
	else
		fc_result_lower = &fc_lower2;

	if (range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2) <= 0)
		fc_result_upper = &fc_upper1;
	else
		fc_result_upper = &fc_upper2;

	return make_range(fc_typcache, fc_result_lower, fc_result_upper, false);
}

/* 范围，范围 -> 范围，范围函数 */

/*
 * range_split_internal - 如果 r2 与 r1 的中间部分相交，
 * 在两侧留下非空范围，则返回 true，并将 output1 和 output2 设置为
 * r1 - r2 的结果（按顺序）。否则返回 false，并且不设置 output1
 * 或 output2。两个输入范围都不应为空。
 */
bool range_split_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2,
					 RangeType **fc_output1, RangeType **fc_output2)
{
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) < 0 &&
		range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2) > 0)
	{
		/*
		 * 需要对 lower2 和 upper2
		 * 点进行包含/排除的翻转。但它们不能是无限的。
		 * 我们可以覆盖这些 RangeBounds，因为它们仅在本地存在。
		 */
		fc_lower2.inclusive = !fc_lower2.inclusive;
		fc_lower2.lower = false;
		fc_upper2.inclusive = !fc_upper2.inclusive;
		fc_upper2.lower = true;

		*fc_output1 = make_range(fc_typcache, &fc_lower1, &fc_lower2, false);
		*fc_output2 = make_range(fc_typcache, &fc_upper2, &fc_upper1, false);
		return true;
	}

	return false;
}

/* 范围 -> 范围聚合函数 */

Datum range_intersect_agg_transfn(PG_FUNCTION_ARGS)
{
	MemoryContext fc_aggContext;
	Oid			fc_rngtypoid;
	TypeCacheEntry *fc_typcache;
	RangeType  *fc_result;
	RangeType  *fc_current;

	if (!AggCheckCallContext(fcinfo, &fc_aggContext))
		elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");

	fc_rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
	if (!type_is_range(fc_rngtypoid))
		elog(ERROR, "range_intersect_agg must be called with a range");

	fc_typcache = range_get_typcache(fcinfo, fc_rngtypoid);

	/* 严格性确保这些是非空 */
	fc_result = PG_GETARG_RANGE_P(0);
	fc_current = PG_GETARG_RANGE_P(1);

	fc_result = range_intersect_internal(fc_typcache, fc_result, fc_current);
	PG_RETURN_RANGE_P(fc_result);
}


/* Btree 支持 */

/* btree 比较器 */
Datum range_cmp(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r1 = PG_GETARG_RANGE_P(0);
	RangeType  *fc_r2 = PG_GETARG_RANGE_P(1);
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower1,
				fc_lower2;
	RangeBound	fc_upper1,
				fc_upper2;
	bool		fc_empty1,
				fc_empty2;
	int			fc_cmp;

	check_stack_depth();		/* 当子类型为范围类型时递归 */

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r1));

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 对于 b-tree 使用，空范围在所有其他范围之前排序 */
	if (fc_empty1 && fc_empty2)
		fc_cmp = 0;
	else if (fc_empty1)
		fc_cmp = -1;
	else if (fc_empty2)
		fc_cmp = 1;
	else
	{
		fc_cmp = range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2);
		if (fc_cmp == 0)
			fc_cmp = range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2);
	}

	PG_FREE_IF_COPY(fc_r1, 0);
	PG_FREE_IF_COPY(fc_r2, 1);

	PG_RETURN_INT32(fc_cmp);
}

/* 使用 range_cmp 函数的非等式运算符 */
Datum range_lt(PG_FUNCTION_ARGS)
{
	int			fc_cmp = range_cmp(fcinfo);

	PG_RETURN_BOOL(fc_cmp < 0);
}

Datum range_le(PG_FUNCTION_ARGS)
{
	int			fc_cmp = range_cmp(fcinfo);

	PG_RETURN_BOOL(fc_cmp <= 0);
}

Datum range_ge(PG_FUNCTION_ARGS)
{
	int			fc_cmp = range_cmp(fcinfo);

	PG_RETURN_BOOL(fc_cmp >= 0);
}

Datum range_gt(PG_FUNCTION_ARGS)
{
	int			fc_cmp = range_cmp(fcinfo);

	PG_RETURN_BOOL(fc_cmp > 0);
}

/* 哈希支持 */

/* 哈希一个范围值 */
Datum hash_range(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r = PG_GETARG_RANGE_P(0);
	uint32		fc_result;
	TypeCacheEntry *fc_typcache;
	TypeCacheEntry *fc_scache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;
	char		fc_flags;
	uint32		fc_lower_hash;
	uint32		fc_upper_hash;

	check_stack_depth();		/* 当子类型为范围类型时递归 */

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	/* 反序列化 */
	range_deserialize(fc_typcache, fc_r, &fc_lower, &fc_upper, &fc_empty);
	fc_flags = range_get_flags(fc_r);

	/*
	 * 查找元素类型的哈希函数，如果尚未完成。
	 */
	fc_scache = fc_typcache->rngelemtype;
	if (!OidIsValid(fc_scache->hash_proc_finfo.fn_oid))
	{
		fc_scache = lookup_type_cache(fc_scache->type_id, TYPECACHE_HASH_PROC_FINFO);
		if (!OidIsValid(fc_scache->hash_proc_finfo.fn_oid))
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
					 errmsg("could not identify a hash function for type %s",
							format_type_be(fc_scache->type_id))));
	}

	/*
	 * 对每个边界应用哈希函数。
	 */
	if (RANGE_HAS_LBOUND(fc_flags))
		fc_lower_hash = DatumGetUInt32(FunctionCall1Coll(&fc_scache->hash_proc_finfo,
													  fc_typcache->rng_collation,
													  fc_lower.val));
	else
		fc_lower_hash = 0;

	if (RANGE_HAS_UBOUND(fc_flags))
		fc_upper_hash = DatumGetUInt32(FunctionCall1Coll(&fc_scache->hash_proc_finfo,
													  fc_typcache->rng_collation,
													  fc_upper.val));
	else
		fc_upper_hash = 0;

	/* 合并标志和边界的哈希 */
	fc_result = hash_uint32((uint32) fc_flags);
	fc_result ^= fc_lower_hash;
	fc_result = pg_rotate_left32(fc_result, 1);
	fc_result ^= fc_upper_hash;

	PG_RETURN_INT32(fc_result);
}

/*
 * 通过将值哈希到 64 位值来返回 64 位值，带有种子。
 * 否则，与 hash_range 类似。
 */
Datum hash_range_extended(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r = PG_GETARG_RANGE_P(0);
	Datum		fc_seed = PG_GETARG_DATUM(1);
	uint64		fc_result;
	TypeCacheEntry *fc_typcache;
	TypeCacheEntry *fc_scache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;
	char		fc_flags;
	uint64		fc_lower_hash;
	uint64		fc_upper_hash;

	check_stack_depth();

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	range_deserialize(fc_typcache, fc_r, &fc_lower, &fc_upper, &fc_empty);
	fc_flags = range_get_flags(fc_r);

	fc_scache = fc_typcache->rngelemtype;
	if (!OidIsValid(fc_scache->hash_extended_proc_finfo.fn_oid))
	{
		fc_scache = lookup_type_cache(fc_scache->type_id,
								   TYPECACHE_HASH_EXTENDED_PROC_FINFO);
		if (!OidIsValid(fc_scache->hash_extended_proc_finfo.fn_oid))
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FUNCTION),
					 errmsg("could not identify a hash function for type %s",
							format_type_be(fc_scache->type_id))));
	}

	if (RANGE_HAS_LBOUND(fc_flags))
		fc_lower_hash = DatumGetUInt64(FunctionCall2Coll(&fc_scache->hash_extended_proc_finfo,
													  fc_typcache->rng_collation,
													  fc_lower.val,
													  fc_seed));
	else
		fc_lower_hash = 0;

	if (RANGE_HAS_UBOUND(fc_flags))
		fc_upper_hash = DatumGetUInt64(FunctionCall2Coll(&fc_scache->hash_extended_proc_finfo,
													  fc_typcache->rng_collation,
													  fc_upper.val,
													  fc_seed));
	else
		fc_upper_hash = 0;

	/* 合并标志和边界的哈希 */
	fc_result = DatumGetUInt64(hash_uint32_extended((uint32) fc_flags,
												 DatumGetInt64(fc_seed)));
	fc_result ^= fc_lower_hash;
	fc_result = ROTATE_HIGH_AND_LOW_32BITS(fc_result);
	fc_result ^= fc_upper_hash;

	PG_RETURN_UINT64(fc_result);
}

/*
 *----------------------------------------------------------
 * 规范函数
 *
 *	 针对特定内置范围类型的函数。
 *----------------------------------------------------------
 */

Datum int4range_canonical(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r = PG_GETARG_RANGE_P(0);
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	range_deserialize(fc_typcache, fc_r, &fc_lower, &fc_upper, &fc_empty);

	if (fc_empty)
		PG_RETURN_RANGE_P(fc_r);

	if (!fc_lower.infinite && !fc_lower.inclusive)
	{
		fc_lower.val = DirectFunctionCall2(int4pl, fc_lower.val, Int32GetDatum(1));
		fc_lower.inclusive = true;
	}

	if (!fc_upper.infinite && fc_upper.inclusive)
	{
		fc_upper.val = DirectFunctionCall2(int4pl, fc_upper.val, Int32GetDatum(1));
		fc_upper.inclusive = false;
	}

	PG_RETURN_RANGE_P(range_serialize(fc_typcache, &fc_lower, &fc_upper, false));
}

Datum int8range_canonical(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r = PG_GETARG_RANGE_P(0);
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	range_deserialize(fc_typcache, fc_r, &fc_lower, &fc_upper, &fc_empty);

	if (fc_empty)
		PG_RETURN_RANGE_P(fc_r);

	if (!fc_lower.infinite && !fc_lower.inclusive)
	{
		fc_lower.val = DirectFunctionCall2(int8pl, fc_lower.val, Int64GetDatum(1));
		fc_lower.inclusive = true;
	}

	if (!fc_upper.infinite && fc_upper.inclusive)
	{
		fc_upper.val = DirectFunctionCall2(int8pl, fc_upper.val, Int64GetDatum(1));
		fc_upper.inclusive = false;
	}

	PG_RETURN_RANGE_P(range_serialize(fc_typcache, &fc_lower, &fc_upper, false));
}

Datum daterange_canonical(PG_FUNCTION_ARGS)
{
	RangeType  *fc_r = PG_GETARG_RANGE_P(0);
	TypeCacheEntry *fc_typcache;
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;

	fc_typcache = range_get_typcache(fcinfo, RangeTypeGetOid(fc_r));

	range_deserialize(fc_typcache, fc_r, &fc_lower, &fc_upper, &fc_empty);

	if (fc_empty)
		PG_RETURN_RANGE_P(fc_r);

	if (!fc_lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(fc_lower.val)) &&
		!fc_lower.inclusive)
	{
		fc_lower.val = DirectFunctionCall2(date_pli, fc_lower.val, Int32GetDatum(1));
		fc_lower.inclusive = true;
	}

	if (!fc_upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(fc_upper.val)) &&
		fc_upper.inclusive)
	{
		fc_upper.val = DirectFunctionCall2(date_pli, fc_upper.val, Int32GetDatum(1));
		fc_upper.inclusive = false;
	}

	PG_RETURN_RANGE_P(range_serialize(fc_typcache, &fc_lower, &fc_upper, false));
}

/*
 *----------------------------------------------------------
 * 子类型差异函数
 *
 * 针对特定内置范围类型的函数。
 *
 * 注意 subtype_diff 会返回差异，而不是差异的绝对值，
 * 并且必须注意避免溢出。
 * (numrange_subdiff 在这方面有一些风险 ...)
 *----------------------------------------------------------
 */

Datum int4range_subdiff(PG_FUNCTION_ARGS)
{
	int32		fc_v1 = PG_GETARG_INT32(0);
	int32		fc_v2 = PG_GETARG_INT32(1);

	PG_RETURN_FLOAT8((float8) fc_v1 - (float8) fc_v2);
}

Datum int8range_subdiff(PG_FUNCTION_ARGS)
{
	int64		fc_v1 = PG_GETARG_INT64(0);
	int64		fc_v2 = PG_GETARG_INT64(1);

	PG_RETURN_FLOAT8((float8) fc_v1 - (float8) fc_v2);
}

Datum numrange_subdiff(PG_FUNCTION_ARGS)
{
	Datum		fc_v1 = PG_GETARG_DATUM(0);
	Datum		fc_v2 = PG_GETARG_DATUM(1);
	Datum		fc_numresult;
	float8		fc_floatresult;

	fc_numresult = DirectFunctionCall2(numeric_sub, fc_v1, fc_v2);

	fc_floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
													 fc_numresult));

	PG_RETURN_FLOAT8(fc_floatresult);
}

Datum daterange_subdiff(PG_FUNCTION_ARGS)
{
	int32		fc_v1 = PG_GETARG_INT32(0);
	int32		fc_v2 = PG_GETARG_INT32(1);

	PG_RETURN_FLOAT8((float8) fc_v1 - (float8) fc_v2);
}

Datum tsrange_subdiff(PG_FUNCTION_ARGS)
{
	Timestamp	fc_v1 = PG_GETARG_TIMESTAMP(0);
	Timestamp	fc_v2 = PG_GETARG_TIMESTAMP(1);
	float8		fc_result;

	fc_result = ((float8) fc_v1 - (float8) fc_v2) / USECS_PER_SEC;
	PG_RETURN_FLOAT8(fc_result);
}

Datum tstzrange_subdiff(PG_FUNCTION_ARGS)
{
	Timestamp	fc_v1 = PG_GETARG_TIMESTAMP(0);
	Timestamp	fc_v2 = PG_GETARG_TIMESTAMP(1);
	float8		fc_result;

	fc_result = ((float8) fc_v1 - (float8) fc_v2) / USECS_PER_SEC;
	PG_RETURN_FLOAT8(fc_result);
}

/*
 *----------------------------------------------------------
 * 支持函数
 *
 *	 这些函数不在 pg_proc 中，但对于
 *	 在 C 中定义新的通用范围函数是有用的。
 *----------------------------------------------------------
 */

/*
 * range_get_typcache: 获取有关范围类型的缓存信息
 *
 * 这供范围相关函数使用，它们遵循使用
 * fn_extra 字段作为指向范围类型的类型缓存条目的指针的约定。
 * 需要缓存比这更多信息的函数必须自行处理。
 */
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid fc_rngtypid)
{
	TypeCacheEntry *fc_typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;

	if (fc_typcache == NULL ||
		fc_typcache->type_id != fc_rngtypid)
	{
		fc_typcache = lookup_type_cache(fc_rngtypid, TYPECACHE_RANGE_INFO);
		if (fc_typcache->rngelemtype == NULL)
			elog(ERROR, "type %u is not a range type", fc_rngtypid);
		fcinfo->flinfo->fn_extra = (void *) fc_typcache;
	}

	return fc_typcache;
}

/*
 * range_serialize: 从边界和空标志构造范围值
 *
 * 这不会强制范围值的规范化。在大多数情况下，
 * 外部调用者应该只调用规范化函数。请注意，
 * 我们在任何情况下都会执行一些数据类型无关的规范化检查。
 */
RangeType * range_serialize(TypeCacheEntry *fc_typcache, RangeBound *fc_lower, RangeBound *fc_upper,
				bool fc_empty)
{
	RangeType  *fc_range;
	int			fc_cmp;
	Size		fc_msize;
	Pointer		fc_ptr;
	int16		fc_typlen;
	bool		fc_typbyval;
	char		fc_typalign;
	char		fc_typstorage;
	char		fc_flags = 0;

	/*
	 * 验证范围在表面上是否合法，并构造标志值，
	 * 以防止任何非规范组合，例如无限+包含。
	 */
	Assert(fc_lower->lower);
	Assert(!fc_upper->lower);

	if (fc_empty)
		fc_flags |= RANGE_EMPTY;
	else
	{
		fc_cmp = range_cmp_bound_values(fc_typcache, fc_lower, fc_upper);

		/* 错误检查：如果下限值高于上限，则错误 */
		if (fc_cmp > 0)
			ereport(ERROR,
					(errcode(ERRCODE_DATA_EXCEPTION),
					 errmsg("range lower bound must be less than or equal to range upper bound")));

		/* 如果边界相等且不是都包含，则范围为空 */
		if (fc_cmp == 0 && !(fc_lower->inclusive && fc_upper->inclusive))
			fc_flags |= RANGE_EMPTY;
		else
		{
			/* 无限边界从不包含 */
			if (fc_lower->infinite)
				fc_flags |= RANGE_LB_INF;
			else if (fc_lower->inclusive)
				fc_flags |= RANGE_LB_INC;
			if (fc_upper->infinite)
				fc_flags |= RANGE_UB_INF;
			else if (fc_upper->inclusive)
				fc_flags |= RANGE_UB_INC;
		}
	}

	/* 获取有关范围元素类型的信息 */
	fc_typlen = fc_typcache->rngelemtype->typlen;
	fc_typbyval = fc_typcache->rngelemtype->typbyval;
	fc_typalign = fc_typcache->rngelemtype->typalign;
	fc_typstorage = fc_typcache->rngelemtype->typstorage;

	/* 计算 varlena 头部和范围类型的 OID 的空间 */
	fc_msize = sizeof(RangeType);
	Assert(fc_msize == MAXALIGN(fc_msize));

	/* 计算边界的空间 */
	if (RANGE_HAS_LBOUND(fc_flags))
	{
		/*
		 * 确保要插入的项未被吐司化。确保我们不将
		 * 超出行的吐司值指针插入范围对象是至关重要的，
		 * 原因与数组和记录不能包含它们相同。
		 * 存储压缩的内联值是可以的，但我们更喜欢先解压
		 * 然后在必要时对整个范围对象进行压缩。
		 * 但与数组不同，我们确实允许短头 varlena 对象保持不变。
		 */
		if (fc_typlen == -1)
			fc_lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(fc_lower->val));

		fc_msize = fc_datum_compute_size(fc_msize, fc_lower->val, fc_typbyval, fc_typalign,
								   fc_typlen, fc_typstorage);
	}

	if (RANGE_HAS_UBOUND(fc_flags))
	{
		/* 确保要插入的项未被吐司化 */
		if (fc_typlen == -1)
			fc_upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(fc_upper->val));

		fc_msize = fc_datum_compute_size(fc_msize, fc_upper->val, fc_typbyval, fc_typalign,
								   fc_typlen, fc_typstorage);
	}

	/* 为标志字节添加空间 */
	fc_msize += sizeof(char);

	/* 注意：这里需要零填充，就像在堆元组中一样 */
	fc_range = (RangeType *) palloc0(fc_msize);
	SET_VARSIZE(fc_range, fc_msize);

	/* 现在填充数据项 */
	fc_range->rangetypid = fc_typcache->type_id;

	fc_ptr = (char *) (fc_range + 1);

	if (RANGE_HAS_LBOUND(fc_flags))
	{
		Assert(fc_lower->lower);
		fc_ptr = fc_datum_write(fc_ptr, fc_lower->val, fc_typbyval, fc_typalign, fc_typlen,
						  fc_typstorage);
	}

	if (RANGE_HAS_UBOUND(fc_flags))
	{
		Assert(!fc_upper->lower);
		fc_ptr = fc_datum_write(fc_ptr, fc_upper->val, fc_typbyval, fc_typalign, fc_typlen,
						  fc_typstorage);
	}

	*((char *) fc_ptr) = fc_flags;

	return fc_range;
}

/*
 * range_deserialize: 解构范围值
 *
 * 注意：给定的范围对象必须完全解吐；
 * 它不能有短的 varlena 头。
 *
 * 请注意，如果元素类型是按引用传递的，RangeBound 结构中的
 * 数据项将是指向给定范围对象的指针。
 */
void range_deserialize(TypeCacheEntry *fc_typcache, const RangeType *fc_range,
				  RangeBound *fc_lower, RangeBound *fc_upper, bool *fc_empty)
{
	char		fc_flags;
	int16		fc_typlen;
	bool		fc_typbyval;
	char		fc_typalign;
	Pointer		fc_ptr;
	Datum		fc_lbound;
	Datum		fc_ubound;

	/* 确保调用者传递了正确的 typcache 条目 */
	Assert(RangeTypeGetOid(fc_range) == fc_typcache->type_id);

	/* 从datum的最后一个字节提取标志字节 */
	fc_flags = *((const char *) fc_range + VARSIZE(fc_range) - 1);

	/* 获取范围元素类型的信息 */
	fc_typlen = fc_typcache->rngelemtype->typlen;
	fc_typbyval = fc_typcache->rngelemtype->typbyval;
	fc_typalign = fc_typcache->rngelemtype->typalign;

	/* 在范围OID之后初始化数据指针 */
	fc_ptr = (Pointer) (fc_range + 1);

	/* 如果有，获取下界 */
	if (RANGE_HAS_LBOUND(fc_flags))
	{
		/* att_align_pointer 在这里可能不是必要的 */
		fc_lbound = fetch_att(fc_ptr, fc_typbyval, fc_typlen);
		fc_ptr = (Pointer) att_addlength_pointer(fc_ptr, fc_typlen, fc_ptr);
	}
	else
		fc_lbound = (Datum) 0;

	/* 获取上限，如果有的话 */
	if (RANGE_HAS_UBOUND(fc_flags))
	{
		fc_ptr = (Pointer) att_align_pointer(fc_ptr, fc_typalign, fc_typlen, fc_ptr);
		fc_ubound = fetch_att(fc_ptr, fc_typbyval, fc_typlen);
		/* 不需要 att_addlength_pointer */
	}
	else
		fc_ubound = (Datum) 0;

	/* 发出结果 */

	*fc_empty = (fc_flags & RANGE_EMPTY) != 0;

	fc_lower->val = fc_lbound;
	fc_lower->infinite = (fc_flags & RANGE_LB_INF) != 0;
	fc_lower->inclusive = (fc_flags & RANGE_LB_INC) != 0;
	fc_lower->lower = true;

	fc_upper->val = fc_ubound;
	fc_upper->infinite = (fc_flags & RANGE_UB_INF) != 0;
	fc_upper->inclusive = (fc_flags & RANGE_UB_INC) != 0;
	fc_upper->lower = false;
}

/*
 * range_get_flags：仅从RangeType值中获取标志。
 *
 * 这在只需要标志而不需要
 * 完整的range_deserialize结果的地方非常有用。
 */ 
char range_get_flags(const RangeType *fc_range)
{
	/* 从datum的最后一个字节提取标志字节 */
	return *((char *) fc_range + VARSIZE(fc_range) - 1);
}

/*
 * range_set_contain_empty：在值中设置RANGE_CONTAIN_EMPTY位。
 *
 * 这仅在GiST操作中需要，因此我们在range_serialize中不包含
 * 设置的条款；相反，必须在之后应用此函数。
 */
void range_set_contain_empty(RangeType *fc_range)
{
	char	   *fc_flagsp;

	/* 标志字节是datum的最后一个字节 */
	fc_flagsp = (char *) fc_range + VARSIZE(fc_range) - 1;

	*fc_flagsp |= RANGE_CONTAIN_EMPTY;
}

/*
 * 这同时序列化和规范化（如果适用）范围。
 * 大多数调用者都应该使用这个。
 */ 
RangeType * make_range(TypeCacheEntry *fc_typcache, RangeBound *fc_lower, RangeBound *fc_upper,
		   bool fc_empty)
{
	RangeType  *fc_range;

	fc_range = range_serialize(fc_typcache, fc_lower, fc_upper, fc_empty);

	/* 对于空范围，没必要调用规范化... */
	if (OidIsValid(fc_typcache->rng_canonical_finfo.fn_oid) &&
		!RangeIsEmpty(fc_range))
		fc_range = DatumGetRangeTypeP(FunctionCall1(&fc_typcache->rng_canonical_finfo,
												 RangeTypePGetDatum(fc_range)));

	return fc_range;
}

/*
 * 比较两个范围边界点，根据
 * b1是否小于、等于或大于b2返回<0, 0或>0。
 *
 * 边界可以是上限和下限的任意组合；因此对
 * 各种操作符都很有用。
 *
 * 简单情况是当b1和b2都是有限且包含的，在这种
 * 情况下结果只是对b1和b2中持有的值的比较。
 *
 * 如果一个边界是排除的，那么我们需要知道它是下限，
 * 在这种情况下我们将边界点视为“刚好大于”持有
 * 值的情况；或者是上限，在这种情况下我们将边界点视为
 * “刚好小于”持有值的情况。
 *
 * 如果一个边界是无限的，它代表负无穷大（小于所有其他
 * 点），如果它是下限；或者正无穷大（大于所有其他
 * 点），如果它是上限。
 *
 * 只有一种情况是两个边界比较相等但并不
 * 相同：当两个边界都是包含的并且持有相同的有限值，
 * 但一个是上限，另一个是下限。
 */
int range_cmp_bounds(TypeCacheEntry *fc_typcache, const RangeBound *fc_b1, const RangeBound *fc_b2)
{
	int32		fc_result;

	/*
	 * 首先，处理涉及无穷大的情况，这不需要调用
	 * 比较程序。
	 */ 
	if (fc_b1->infinite && fc_b2->infinite)
	{
		/*
		 * 都是无穷大，因此它们是相等的，除非一个是下限而
		 * 另一个不是。
		 */ 
		if (fc_b1->lower == fc_b2->lower)
			return 0;
		else
			return fc_b1->lower ? -1 : 1;
	}
	else if (fc_b1->infinite)
		return fc_b1->lower ? -1 : 1;
	else if (fc_b2->infinite)
		return fc_b2->lower ? 1 : -1;

	/*
	 * 两个边界都是有限的，因此比较持有的值。
	 */ 
	fc_result = DatumGetInt32(FunctionCall2Coll(&fc_typcache->rng_cmp_proc_finfo,
											 fc_typcache->rng_collation,
											 fc_b1->val, fc_b2->val));

	/*
	 * 如果比较结果不是相等，则完成。如果它们比较相等，
	 * 我们仍然需要考虑边界是否是包含的或排除的。
	 */ 
	if (fc_result == 0)
	{
		if (!fc_b1->inclusive && !fc_b2->inclusive)
		{
			/* 两者都是排除的 */
			if (fc_b1->lower == fc_b2->lower)
				return 0;
			else
				return fc_b1->lower ? 1 : -1;
		}
		else if (!fc_b1->inclusive)
			return fc_b1->lower ? 1 : -1;
		else if (!fc_b2->inclusive)
			return fc_b2->lower ? -1 : 1;
		else
		{
			/*
			 * 两者都是包含的且持有的值相等，因此它们是
			 * 相等的，无论它们是上限还是下限，
			 * 或者混合。
			 */ 
			return 0;
		}
	}

	return fc_result;
}

/*
 * 比较两个范围边界点值，根据
 * b1是否小于、等于或大于b2返回<0, 0或>0。
 *
 * 这类似但比range_cmp_bounds()简单。我们只比较
 * b1和b2中持有的值，忽略包含/排除标志。
 * 下限/上限标志仅对无穷大有意义，它告诉我们
 * 无穷大是正还是负。
 */
int range_cmp_bound_values(TypeCacheEntry *fc_typcache, const RangeBound *fc_b1,
					   const RangeBound *fc_b2)
{
	/*
	 * 首先，处理涉及无穷大的情况，这不需要调用
	 * 比较程序。
	 */ 
	if (fc_b1->infinite && fc_b2->infinite)
	{
		/*
		 * 都是无穷大，因此它们是相等的，除非一个是下限而
		 * 另一个不是。
		 */ 
		if (fc_b1->lower == fc_b2->lower)
			return 0;
		else
			return fc_b1->lower ? -1 : 1;
	}
	else if (fc_b1->infinite)
		return fc_b1->lower ? -1 : 1;
	else if (fc_b2->infinite)
		return fc_b2->lower ? 1 : -1;

	/*
	 * 两个边界都是有限的，因此比较持有的值。
	 */ 
	return DatumGetInt32(FunctionCall2Coll(&fc_typcache->rng_cmp_proc_finfo,
										   fc_typcache->rng_collation,
										   fc_b1->val, fc_b2->val));
}

/*
 * qsort回调函数，用于排序范围。
 *
 * 两个空范围相等；一个空范围在任何非空范围的左边。
 * 两个非空范围根据下限优先排序，接着是上限。
 */
int range_compare(const void *fc_key1, const void *fc_key2, void *fc_arg)
{
	RangeType  *fc_r1 = *(RangeType **) fc_key1;
	RangeType  *fc_r2 = *(RangeType **) fc_key2;
	TypeCacheEntry *fc_typcache = (TypeCacheEntry *) fc_arg;
	RangeBound	fc_lower1;
	RangeBound	fc_upper1;
	RangeBound	fc_lower2;
	RangeBound	fc_upper2;
	bool		fc_empty1;
	bool		fc_empty2;
	int			fc_cmp;

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	if (fc_empty1 && fc_empty2)
		fc_cmp = 0;
	else if (fc_empty1)
		fc_cmp = -1;
	else if (fc_empty2)
		fc_cmp = 1;
	else
	{
		fc_cmp = range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2);
		if (fc_cmp == 0)
			fc_cmp = range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2);
	}

	return fc_cmp;
}

/*
 * 构建一个类型由typcache条目指示的空范围值。
 */
RangeType * make_empty_range(TypeCacheEntry *fc_typcache)
{
	RangeBound	fc_lower;
	RangeBound	fc_upper;

	fc_lower.val = (Datum) 0;
	fc_lower.infinite = false;
	fc_lower.inclusive = false;
	fc_lower.lower = true;

	fc_upper.val = (Datum) 0;
	fc_upper.infinite = false;
	fc_upper.inclusive = false;
	fc_upper.lower = false;

	return make_range(fc_typcache, &fc_lower, &fc_upper, true);
}


/*
 *----------------------------------------------------------
 * 静态函数
 *----------------------------------------------------------
 */

/*
 * 给定一个表示范围类型标志的字符串，返回作为字符表示的标志。
 */
static char fc_range_parse_flags(const char *fc_flags_str)
{
	char		fc_flags = 0;

	if (fc_flags_str[0] == '\0' ||
		fc_flags_str[1] == '\0' ||
		fc_flags_str[2] != '\0')
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("invalid range bound flags"),
				 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));

	switch (fc_flags_str[0])
	{
		case '[':
			fc_flags |= RANGE_LB_INC;
			break;
		case '(':
			break;
		default:
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("invalid range bound flags"),
					 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
	}

	switch (fc_flags_str[1])
	{
		case ']':
			fc_flags |= RANGE_UB_INC;
			break;
		case ')':
			break;
		default:
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("invalid range bound flags"),
					 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
	}

	return fc_flags;
}

/*
 * 解析范围输入。
 *
 * 输入参数：
 *	string：要解析的输入字符串
 * 输出参数：
 *	*flags：接收标志位掩码
 *	*lbound_str：接收palloc分配的下限字符串，如果没有则为NULL
 *	*ubound_str：接收palloc分配的上限字符串，如果没有则为NULL
 *
 * 这在某种程度上模仿了rowtypes.c中的record_in。
 * 输入语法是：
 *	<range>   := EMPTY
 *			   | <lb-inc> <string>, <string> <ub-inc>
 *	<lb-inc>  := '[' | '('
 *	<ub-inc>  := ']' | ')'
 *
 * <range>前后的空格会被忽略。<string>内的空格
 * 是字面意思，并成为该边界的输入字符串的一部分。
 *
 * 长度为零的<string>被视为“无限”（即没有边界），除非
 * 它被双引号包围，在这种情况下它是字面上空的
 * 字符串。
 *
 * 在<string>内，特殊字符（如逗号、括号或
 * 方括号）可以被双引号括起来或用反斜杠转义。在
 * 双引号内，双引号可以用双引号或反斜杠转义。
 */
static void fc_range_parse(const char *fc_string, char *fc_flags, char **fc_lbound_str,
			char **fc_ubound_str)
{
	const char *fc_ptr = fc_string;
	bool		fc_infinite;

	*fc_flags = 0;

	/* 消耗空白 */
	while (*fc_ptr != '\0' && isspace((unsigned char) *fc_ptr))
		fc_ptr++;

	/* 检查空范围 */
	if (pg_strncasecmp(fc_ptr, RANGE_EMPTY_LITERAL,
					   strlen(RANGE_EMPTY_LITERAL)) == 0)
	{
		*fc_flags = RANGE_EMPTY;
		*fc_lbound_str = NULL;
		*fc_ubound_str = NULL;

		fc_ptr += strlen(RANGE_EMPTY_LITERAL);

		/* 剩下的应该是空格 */
		while (*fc_ptr != '\0' && isspace((unsigned char) *fc_ptr))
			fc_ptr++;

		/* 应该已经消耗了所有内容 */
		if (*fc_ptr != '\0')
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
					 errmsg("malformed range literal: \"%s\"",
							fc_string),
					 errdetail("Junk after \"empty\" key word.")));

		return;
	}

	if (*fc_ptr == '[')
	{
		*fc_flags |= RANGE_LB_INC;
		fc_ptr++;
	}
	else if (*fc_ptr == '(')
		fc_ptr++;
	else
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
				 errmsg("malformed range literal: \"%s\"",
						fc_string),
				 errdetail("Missing left parenthesis or bracket.")));

	fc_ptr = fc_range_parse_bound(fc_string, fc_ptr, fc_lbound_str, &fc_infinite);
	if (fc_infinite)
		*fc_flags |= RANGE_LB_INF;

	if (*fc_ptr == ',')
		fc_ptr++;
	else
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
				 errmsg("malformed range literal: \"%s\"",
						fc_string),
				 errdetail("Missing comma after lower bound.")));

	fc_ptr = fc_range_parse_bound(fc_string, fc_ptr, fc_ubound_str, &fc_infinite);
	if (fc_infinite)
		*fc_flags |= RANGE_UB_INF;

	if (*fc_ptr == ']')
	{
		*fc_flags |= RANGE_UB_INC;
		fc_ptr++;
	}
	else if (*fc_ptr == ')')
		fc_ptr++;
	else						/* 必须是一个逗号 */
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
				 errmsg("malformed range literal: \"%s\"",
						fc_string),
				 errdetail("Too many commas.")));

	/* 消耗空白 */
	while (*fc_ptr != '\0' && isspace((unsigned char) *fc_ptr))
		fc_ptr++;

	if (*fc_ptr != '\0')
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
				 errmsg("malformed range literal: \"%s\"",
						fc_string),
				 errdetail("Junk after right parenthesis or bracket.")));
}


/*
 * 帮助函数 range_parse：解析并去掉一个边界字符串的引号。
 *
 * 我们扫描，直到找到逗号、右括号或右中括号。
 *
 * 输入参数：
 *	string：整个输入字符串（仅用于错误报告）
 *	ptr：开始解析边界的位置
 * 输出参数：
 *	*bound_str：接收分配的边界字符串，如果没有则为 NULL
 *	*infinite：如果没有边界则设置为 true，否则为 false
 *
 * 返回值是扫描指针，已推进到边界字符串之后。
 */
static const char * fc_range_parse_bound(const char *fc_string, const char *fc_ptr,
				  char **fc_bound_str, bool *fc_infinite)
{
	StringInfoData fc_buf;

	/* 检查空值：完全空的输入意味着 null */
	if (*fc_ptr == ',' || *fc_ptr == ')' || *fc_ptr == ']')
	{
		*fc_bound_str = NULL;
		*fc_infinite = true;
	}
	else
	{
		/* 提取此边界的字符串 */
		bool		fc_inquote = false;

		initStringInfo(&fc_buf);
		while (fc_inquote || !(*fc_ptr == ',' || *fc_ptr == ')' || *fc_ptr == ']'))
		{
			char		fc_ch = *fc_ptr++;

			if (fc_ch == '\0')
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
						 errmsg("malformed range literal: \"%s\"",
								fc_string),
						 errdetail("Unexpected end of input.")));
			if (fc_ch == '\\')
			{
				if (*fc_ptr == '\0')
					ereport(ERROR,
							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
							 errmsg("malformed range literal: \"%s\"",
									fc_string),
							 errdetail("Unexpected end of input.")));
				appendStringInfoChar(&fc_buf, *fc_ptr++);
			}
			else if (fc_ch == '"')
			{
				if (!fc_inquote)
					fc_inquote = true;
				else if (*fc_ptr == '"')
				{
					/* 引号序列中的双引号 */
					appendStringInfoChar(&fc_buf, *fc_ptr++);
				}
				else
					fc_inquote = false;
			}
			else
				appendStringInfoChar(&fc_buf, fc_ch);
		}

		*fc_bound_str = fc_buf.data;
		*fc_infinite = false;
	}

	return fc_ptr;
}

/*
 * 将反序列化的范围值转换为文本形式
 *
 * 输入为标志字节和两个已转换为文本的边界值（但尚未加引号）。如果没有边界值，传入 NULL。
 *
 * 结果是分配的字符串
 */
static char * fc_range_deparse(char fc_flags, const char *fc_lbound_str, const char *fc_ubound_str)
{
	StringInfoData fc_buf;

	if (fc_flags & RANGE_EMPTY)
		return pstrdup(RANGE_EMPTY_LITERAL);

	initStringInfo(&fc_buf);

	appendStringInfoChar(&fc_buf, (fc_flags & RANGE_LB_INC) ? '[' : '(');

	if (RANGE_HAS_LBOUND(fc_flags))
		appendStringInfoString(&fc_buf, fc_range_bound_escape(fc_lbound_str));

	appendStringInfoChar(&fc_buf, ',');

	if (RANGE_HAS_UBOUND(fc_flags))
		appendStringInfoString(&fc_buf, fc_range_bound_escape(fc_ubound_str));

	appendStringInfoChar(&fc_buf, (fc_flags & RANGE_UB_INC) ? ']' : ')');

	return fc_buf.data;
}

/*
 * range_deparse 的辅助函数：根据需要对边界值进行引用
 *
 * 结果是一个 palloc' 的字符串
 */
static char * fc_range_bound_escape(const char *fc_value)
{
	bool		fc_nq;
	const char *fc_ptr;
	StringInfoData fc_buf;
#ifdef FDD//cppcheck
	if (NULL == fc_value)
		return NULL;
#endif
	initStringInfo(&fc_buf);

	/* 检测是否需要为该值添加双引号 */
	fc_nq = (fc_value[0] == '\0');	/* 强制对空字符串使用引号 */
	for (fc_ptr = fc_value; *fc_ptr; fc_ptr++)
	{
		char		fc_ch = *fc_ptr;

		if (fc_ch == '"' || fc_ch == '\\' ||
			fc_ch == '(' || fc_ch == ')' ||
			fc_ch == '[' || fc_ch == ']' ||
			fc_ch == ',' ||
			isspace((unsigned char) fc_ch))
		{
			fc_nq = true;
			break;
		}
	}

	/* 并输出字符串 */
	if (fc_nq)
		appendStringInfoChar(&fc_buf, '"');
	for (fc_ptr = fc_value; *fc_ptr; fc_ptr++)
	{
		char		fc_ch = *fc_ptr;

		if (fc_ch == '"' || fc_ch == '\\')
			appendStringInfoChar(&fc_buf, fc_ch);
		appendStringInfoChar(&fc_buf, fc_ch);
	}
	if (fc_nq)
		appendStringInfoChar(&fc_buf, '"');

	return fc_buf.data;
}

/*
 * 测试范围 r1 是否包含范围 r2。
 *
 * 调用者已经检查它们是否是相同的范围类型，并查找了必要的 typcache 条目。
 */
bool range_contains_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	RangeBound	fc_lower1;
	RangeBound	fc_upper1;
	bool		fc_empty1;
	RangeBound	fc_lower2;
	RangeBound	fc_upper2;
	bool		fc_empty2;

	/* 不同类型应通过 ANYRANGE 匹配规则予以防止 */
	if (RangeTypeGetOid(fc_r1) != RangeTypeGetOid(fc_r2))
		elog(ERROR, "range types do not match");

	range_deserialize(fc_typcache, fc_r1, &fc_lower1, &fc_upper1, &fc_empty1);
	range_deserialize(fc_typcache, fc_r2, &fc_lower2, &fc_upper2, &fc_empty2);

	/* 如果任一范围为空，答案很简单 */
	if (fc_empty2)
		return true;
	else if (fc_empty1)
		return false;

	/* 否则我们必须满足 lower1 <= lower2 和 upper1 >= upper2 */
	if (range_cmp_bounds(fc_typcache, &fc_lower1, &fc_lower2) > 0)
		return false;
	if (range_cmp_bounds(fc_typcache, &fc_upper1, &fc_upper2) < 0)
		return false;

	return true;
}

bool range_contained_by_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r1, const RangeType *fc_r2)
{
	return range_contains_internal(fc_typcache, fc_r2, fc_r1);
}

/*
 * 测试范围 r 是否包含特定的元素值。
 */
bool range_contains_elem_internal(TypeCacheEntry *fc_typcache, const RangeType *fc_r, Datum fc_val)
{
	RangeBound	fc_lower;
	RangeBound	fc_upper;
	bool		fc_empty;
	int32		fc_cmp;

	range_deserialize(fc_typcache, fc_r, &fc_lower, &fc_upper, &fc_empty);

	if (fc_empty)
		return false;

	if (!fc_lower.infinite)
	{
		fc_cmp = DatumGetInt32(FunctionCall2Coll(&fc_typcache->rng_cmp_proc_finfo,
											  fc_typcache->rng_collation,
											  fc_lower.val, fc_val));
		if (fc_cmp > 0)
			return false;
		if (fc_cmp == 0 && !fc_lower.inclusive)
			return false;
	}

	if (!fc_upper.infinite)
	{
		fc_cmp = DatumGetInt32(FunctionCall2Coll(&fc_typcache->rng_cmp_proc_finfo,
											  fc_typcache->rng_collation,
											  fc_upper.val, fc_val));
		if (fc_cmp < 0)
			return false;
		if (fc_cmp == 0 && !fc_upper.inclusive)
			return false;
	}

	return true;
}


/*
 * datum_compute_size() 和 datum_write() 用于将边界值插入到范围对象中。
 * 它们是根据 heaptuple.c 的 heap_compute_data_size() 和 heap_fill_tuple() 模型化的，但我们在这里不需要处理 null 值。
 * TYPE_IS_PACKABLE 必须测试与 heaptuple.c 的 ATT_IS_PACKABLE 宏相同的条件。
 * 有关更多详细信息，请参见那里的注释。
 */

/* 数据类型是否允许打包到 1-byte-header varlena 格式？ */
#define TYPE_IS_PACKABLE(typlen, typstorage) \
	((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)

/*
 * 将 data_length 增加到 datum 所需的空间，包括任何前面的对齐填充。
 */
static Size fc_datum_compute_size(Size fc_data_length, Datum fc_val, bool fc_typbyval, char fc_typalign,
				   int16 fc_typlen, char fc_typstorage)
{
	if (TYPE_IS_PACKABLE(fc_typlen, fc_typstorage) &&
		VARATT_CAN_MAKE_SHORT(DatumGetPointer(fc_val)))
	{
		/*
		 * 我们预期会转换为短 varlena 头，因此调整
		 * 长度并且不计算任何对齐
		 */
		fc_data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(fc_val));
	}
	else
	{
		fc_data_length = att_align_datum(fc_data_length, fc_typalign, fc_typlen, fc_val);
		fc_data_length = att_addlength_datum(fc_data_length, fc_typlen, fc_val);
	}

	return fc_data_length;
}

/*
 * 从 ptr 开始写入给定的 datum（如果需要，先调整到正确的对齐）。
 * 返回指针，增加使用的空间。
 */
static Pointer
fc_datum_write(Pointer fc_ptr, Datum fc_datum, bool fc_typbyval, char fc_typalign,
			int16 fc_typlen, char fc_typstorage)
{
	Size		fc_data_length;

	if (fc_typbyval)
	{
		/* 传值引用 */
		fc_ptr = (char *) att_align_nominal(fc_ptr, fc_typalign);
		store_att_byval(fc_ptr, fc_datum, fc_typlen);
		fc_data_length = fc_typlen;
	}
	else if (fc_typlen == -1)
	{
		/* varlena */
		Pointer		fc_val = DatumGetPointer(fc_datum);

		if (VARATT_IS_EXTERNAL(fc_val))
		{
			/*
			 * 抛出错误，因为我们绝不能在范围对象中放置 toast 指针。
			 * 调用者应该已经将其去 toast。
			 */
			elog(ERROR, "cannot store a toast pointer inside a range");
			fc_data_length = 0;	/* 保持编译器安静 */
		}
		else if (VARATT_IS_SHORT(fc_val))
		{
			/* 短varlenas不需要对齐 */
			fc_data_length = VARSIZE_SHORT(fc_val);
			memcpy(fc_ptr, fc_val, fc_data_length);
		}
		else if (TYPE_IS_PACKABLE(fc_typlen, fc_typstorage) &&
				 VARATT_CAN_MAKE_SHORT(fc_val))
		{
			/* 转换为短varlena -- 不需要对齐 */
			fc_data_length = VARATT_CONVERTED_SHORT_SIZE(fc_val);
			SET_VARSIZE_SHORT(fc_ptr, fc_data_length);
			memcpy(fc_ptr + 1, VARDATA(fc_val), fc_data_length - 1);
		}
		else
		{
			/* 完整的4字节头varlena */
			fc_ptr = (char *) att_align_nominal(fc_ptr, fc_typalign);
			fc_data_length = VARSIZE(fc_val);
			memcpy(fc_ptr, fc_val, fc_data_length);
		}
	}
	else if (fc_typlen == -2)
	{
		/* cstring ... 永远不需要对齐 */
		Assert(fc_typalign == TYPALIGN_CHAR);
		fc_data_length = strlen(DatumGetCString(fc_datum)) + 1;
		memcpy(fc_ptr, DatumGetPointer(fc_datum), fc_data_length);
	}
	else
	{
		/* 固定长度的传值引用 */
		fc_ptr = (char *) att_align_nominal(fc_ptr, fc_typalign);
		Assert(fc_typlen > 0);
		fc_data_length = fc_typlen;
		memcpy(fc_ptr, DatumGetPointer(fc_datum), fc_data_length);
	}

	fc_ptr += fc_data_length;

	return fc_ptr;
}
